Skip to content

Backend#274

Merged
longsizhuo merged 17 commits into
mainfrom
backend
Apr 11, 2026
Merged

Backend#274
longsizhuo merged 17 commits into
mainfrom
backend

Conversation

@longsizhuo
Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings April 9, 2026 18:51
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
involutionhell-github-io Ready Ready Preview, Comment Apr 11, 2026 3:05pm
website-preview Ready Ready Preview, Comment Apr 11, 2026 3:05pm

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes NextAuth-based authentication from the Next.js app and switches the frontend to rely on a backend Sa-Token auth flow, with Next.js acting as a proxy for auth-related endpoints. It also updates Prisma models to decouple legacy NextAuth tables from the new user_accounts identity model and to persist chat/analytics user attribution via BigInt IDs.

Changes:

  • Removed NextAuth integration (config, API route, providers) and replaced client auth state with a new AuthProvider/useAuth hook backed by /auth/me.
  • Added Next.js rewrites to proxy OAuth callback and /auth/* routes to the backend, and updated UI components/pages to use the new auth flow.
  • Updated Prisma schema so Chat.userId / AnalyticsEvent.userId use BigInt and no longer relate to the legacy users table.

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
proxy.ts Removed previous auth proxy export/config.
auth.ts Removed NextAuth initialization.
auth.config.ts Removed NextAuth configuration/callbacks.
app/api/auth/[...nextauth]/route.ts Removed NextAuth API handlers route.
package.json Removed next-auth dependency.
pnpm-lock.yaml Lockfile updates reflecting removed next-auth.
next.config.mjs Added rewrites for backend auth/callback proxying.
lib/use-auth.tsx Added client auth context/hook reading token and calling /auth/me.
lib/server-auth.ts Added server helper to resolve user ID via backend /auth/me.
prisma/schema.prisma Annotated legacy NextAuth tables; switched chat/analytics userId to BigInt and removed legacy relations.
app/layout.tsx Replaced SessionProvider with AuthProvider.
app/login/page.tsx Simplified login page to use backend OAuth entrypoint.
app/editor/page.tsx Switched editor gatekeeping to client-side auth.
app/editor/EditorPageClient.tsx Switched from NextAuth session to UserView and added token header for uploads.
app/components/SignInButton.tsx Redirects to backend OAuth render endpoint.
app/components/Header.tsx Moved auth UI to client AuthNav.
app/components/AuthNav.tsx Uses useAuth() to render sign-in vs user menu.
app/components/UserMenu.tsx Uses injected logout() instead of NextAuth signOut.
app/components/UmamiIdentity.tsx Uses useAuth() for Umami identify fields.
app/components/DocsAssistant.tsx Persisted chatId, added per-request x-satoken, and removed client-sent userId.
app/api/upload/route.ts Validates token via backend /auth/me before issuing upload URL.
app/api/chat/route.ts Added backend streaming proxy fallback and binds persisted chat to resolved BigInt userId.
app/api/analytics/route.ts Resolves userId server-side via token and stores BigInt userId.
lib/ai/providers/intern.ts Dev-only remap to Deepseek for testing.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/use-auth.tsx
Comment thread lib/use-auth.tsx Outdated
Comment on lines +60 to +75
// 1. 检查 URL 中是否携带 ?token=xxx(后端 OAuth 登录成功后跳回来时携带)
const params = new URLSearchParams(window.location.search);
const urlToken = params.get("token");

if (urlToken) {
// 存入 localStorage
localStorage.setItem("satoken", urlToken);
// 用 replaceState 清除 URL 中的 token 参数,避免刷新或分享时 token 泄露
params.delete("token");
const newSearch = params.toString();
const newUrl =
window.location.pathname +
(newSearch ? "?" + newSearch : "") +
window.location.hash;
window.history.replaceState(null, "", newUrl);
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auth token is accepted via the ?token= query param and then stored in localStorage. Even with replaceState, query-string tokens can leak via server/access logs and Referer headers, and localStorage makes the token available to any XSS. Consider switching to an OAuth code exchange (or redirect token in URL fragment) and store the session in an HttpOnly cookie instead of localStorage.

Copilot uses AI. Check for mistakes.
Comment thread app/api/chat/route.ts
Comment on lines +39 to +54
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时

// 原封不动把前端的参数丢给 Java
const proxyRes = await fetch(`${backendUrl}/openai/responses/stream`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-satoken": req.headers.get("x-satoken") || "",
},
body: await proxyReq.text(),
signal: controller.signal,
});

clearTimeout(timeoutId);

Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Java-backend proxy attempt, the timeout is only cleared on the success path. If fetch() throws (network error/abort), timeoutId isn’t cleared, leaving a pending timer per request. Use a finally block (or try { ... } finally { clearTimeout(timeoutId) }) to always clear the timeout.

Copilot uses AI. Check for mistakes.
Comment thread app/api/chat/route.ts Outdated
Comment on lines +43 to +49
const proxyRes = await fetch(`${backendUrl}/openai/responses/stream`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-satoken": req.headers.get("x-satoken") || "",
},
body: await proxyReq.text(),
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback proxy forwards the incoming token to the backend as x-satoken, but other backend calls in this PR use satoken (e.g. /auth/me). If the Java backend expects the same satoken header, this will break authenticated proxying. Consider mapping req.headers.get("x-satoken") to an outgoing satoken header (and omit the header entirely when missing).

Copilot uses AI. Check for mistakes.
Comment thread lib/server-auth.ts
Comment on lines +1 to +15
/**
* 服务端身份验证工具函数(仅用于 Next.js API Route / Server Component)
*
* 通过 x-satoken 请求头调用后端 /auth/me 验证身份,
* 返回 user_accounts.id(BigInt),匿名或 token 无效时返回 null。
*
* 使用方:app/api/chat/route.ts、app/api/analytics/route.ts
*/
export async function resolveUserId(req: Request): Promise<bigint | null> {
const token = req.headers.get("x-satoken");
if (!token || !process.env.BACKEND_URL) return null;
try {
const res = await fetch(`${process.env.BACKEND_URL}/auth/me`, {
headers: { satoken: token },
});
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstring says this function calls the backend using the x-satoken header, but the implementation sends satoken. Please update the comment or the header name so the contract is unambiguous (especially since other routes in this PR use both header names).

Copilot uses AI. Check for mistakes.
Comment thread app/api/upload/route.ts Outdated
Comment on lines +39 to +48
// 从请求头读取 satoken,转发给后端验证
const token = request.headers.get("satoken");
if (!token) {
return NextResponse.json({ error: "未授权访问" }, { status: 401 });
}

if (!session?.user?.id) {
// 调用后端 /auth/me 验证 token(服务端直连后端,走 BACKEND_URL 环境变量)
const backendUrl = process.env.BACKEND_URL ?? "http://localhost:8080";
const meRes = await fetch(`${backendUrl}/auth/me`, {
headers: { satoken: token },
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This route expects the client token in a satoken header, while other new client→Next routes use x-satoken (e.g. /api/chat, /api/analytics via resolveUserId). Standardizing on one header name for client→Next requests would reduce confusion and prevent accidental 401s when reusing fetch helpers.

Copilot uses AI. Check for mistakes.
Comment thread app/login/page.tsx
const params = await searchParams;
const redirectTarget = resolveRedirectTarget(params);

export default async function LoginPage({ searchParams: _ }: LoginPageProps) {
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

searchParams is no longer used, but the file still defines FALLBACK_CALLBACK_URL, coerceSearchParam, and resolveRedirectTarget, which will now be unused and trigger lint warnings. Consider removing the unused helpers and simplifying LoginPageProps accordingly.

Copilot uses AI. Check for mistakes.
Comment thread app/editor/page.tsx
Comment on lines +16 to +20
useEffect(() => {
// 状态确认后,未登录则跳转到登录页
if (status === "unauthenticated") {
router.replace("/login?callbackUrl=/editor");
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This redirect still passes callbackUrl=/editor, but the updated login flow no longer uses callbackUrl/redirectTo and always starts OAuth via the backend. Consider removing this query param (or replacing it with whatever the new post-login navigation mechanism is) to avoid implying it’s respected.

Copilot uses AI. Check for mistakes.
@longsizhuo longsizhuo merged commit bc9eaea into main Apr 11, 2026
6 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants